package com.other.generater;

/**
 * 类功能描述:
 *
 * @author baigt
 * @version V1.0
 * @since 2019-04-04 14:53
 */

import sun.net.util.IPAddressUtil;

import java.net.*;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class IpUtils2 {
    private static String local_ipv4 = null;
    public static final Pattern IPv4_PATTERN = Pattern.compile("((?:(?:25[0-5]|2[0-4]\\d|(?:1\\d{2}|[1-9]?\\d))\\.){3}(?:25[0-5]|2[0-4]\\d|(?:1\\d{2}|[1-9]?\\d)))");
    public static final LinkedHashMap<String,String> mapper;
    static {
        mapper = new LinkedHashMap<String,String>() {
            private static final long serialVersionUID = 2102800127289361549L;
            {
                this.put("192.168.1.0/24", "test");
                this.put("192.168.3.0/24", "test");
                this.put("192.168.8.0/24", "test");
                this.put("192.168.9.0/24", "test");
                this.put("192.168.24.0/24", "test");
                this.put("192.168.25.0/24", "test");
                this.put("192.168.26.0/24", "test");
                this.put("192.168.27.0/24", "test");
                this.put("192.168.95.0/24", "test");
                this.put("192.168.96.0/24", "test");
                this.put("192.168.97.0/24", "test");
                this.put("192.168.98.0/24", "test");
                this.put("192.168.99.0/24", "test");
                this.put("10.20.120.0/24", "pre");
                this.put("10.12.1.0/24", "production");
                this.put("10.212.1.0/24", "production");
                this.put("172.20.105.0/24", "production");
                this.put("10.40.100.0/24", "production");
                this.put("172.31.0.0/16", "test");
                this.put("10.20.0.0/16", "production");
                this.put("10.10.0.0/16", "production");
            }
        };
    }
    private IpUtils2() {
    }

    public static String getLocalIP(Class<? extends InetAddress> inetClass) {
        InetAddress localAddress;
        try {
            localAddress = InetAddress.getLocalHost();
            String ipv6;
            if (localAddress instanceof Inet4Address && inetClass == Inet4Address.class && !isReservedAddr(localAddress)) {
                ipv6 = localAddress.getHostAddress();
                if (IPAddressUtil.isIPv4LiteralAddress(ipv6)) {
                    return ipv6;
                }
            }

            if (localAddress instanceof Inet6Address && inetClass == Inet6Address.class && !isReservedAddr(localAddress)) {
                ipv6 = localAddress.getHostAddress();
                if (IPAddressUtil.isIPv6LiteralAddress(ipv6)) {
                    return ipv6;
                }
            }
        } catch (Throwable var7) {
        }

        localAddress = null;

        try {
            Enumeration interfaces = NetworkInterface.getNetworkInterfaces();

            while(true) {
                String iFDisplayName;
                String iName;
                NetworkInterface networkInterface;
                do {
                    do {
                        do {
                            do {
                                if (!interfaces.hasMoreElements()) {
                                    String interfacesStr = buildInterfacesStr(interfaces);
                                    throw new IllegalArgumentException(String.format("未找到本地IP: %s", interfacesStr));
                                }

                                networkInterface = (NetworkInterface)interfaces.nextElement();
                                iFDisplayName = networkInterface.getDisplayName().toLowerCase();
                                iName = networkInterface.getName().toLowerCase();
                            } while(!networkInterface.isUp());
                        } while(iFDisplayName.contains("tap"));
                    } while(iFDisplayName.contains("virtual"));
                } while(!iFDisplayName.startsWith("e") && !iFDisplayName.startsWith("w") && !iFDisplayName.startsWith("b") && !iFDisplayName.startsWith("n") && !iName.startsWith("e") && !iName.startsWith("w") && !iName.startsWith("b") && !iName.startsWith("n"));

                Enumeration inetAddressEnum = networkInterface.getInetAddresses();

                while(inetAddressEnum.hasMoreElements()) {
                    InetAddress inetAddress = (InetAddress)inetAddressEnum.nextElement();
                    if (inetAddress.getClass() == inetClass) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException var8) {
            throw new IllegalArgumentException("获取本地IP出错:" + localAddress, var8);
        }
    }

    private static String buildInterfacesStr(Enumeration<NetworkInterface> interfaces) throws SocketException {
        StringBuffer interfacesStr = new StringBuffer();
        interfaces = NetworkInterface.getNetworkInterfaces();

        while(interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = (NetworkInterface)interfaces.nextElement();
            String iFDisplayName = networkInterface.getDisplayName().toLowerCase();
            String iName = networkInterface.getName().toLowerCase();
            interfacesStr.append("name:").append(iName).append(", displayName:").append(iFDisplayName).append(", isUp:").append(String.valueOf(networkInterface.isUp()));
            if (networkInterface.isUp() && !iFDisplayName.contains("tap") && !iFDisplayName.contains("virtual") && (iFDisplayName.startsWith("e") || iFDisplayName.startsWith("w") || iFDisplayName.startsWith("b") || iFDisplayName.startsWith("n") || iName.startsWith("e") || iName.startsWith("w") || iName.startsWith("b") || iName.startsWith("n"))) {
                interfacesStr.append(" | no continue");
            } else {
                interfacesStr.append(" | continue");
            }

            interfacesStr.append("\r\n");

            for(Enumeration inetAddressEnum = networkInterface.getInetAddresses(); inetAddressEnum.hasMoreElements(); interfacesStr.append("\r\n")) {
                InetAddress inetAddress = (InetAddress)inetAddressEnum.nextElement();
                interfacesStr.append(inetAddress);
                if (inetAddress.getClass() == Inet4Address.class) {
                    interfacesStr.append(" *** is IPv4Address");
                }
            }

            interfacesStr.append("========================================================\r\n");
        }

        return interfacesStr.toString();
    }

    public static String getLocalIPv4() {
        if (local_ipv4 == null) {
            local_ipv4 = getLocalIP(Inet4Address.class);
        }

        return local_ipv4;
    }

    public static Long convertIPv4(String ipStr) {
        if (ipStr != null && !ipStr.isEmpty()) {
            try {
                String[] ipTokens = ipStr.split("\\.");
                if (ipTokens.length != 4) {
                    throw new IllegalArgumentException("IP字符串错误:" + ipStr);
                } else {
                    long ipNum = 0L;

                    for(int i = 0; i < 4; ++i) {
                        ipNum = (ipNum << 8) + (long)Integer.valueOf(ipTokens[i]);
                    }

                    return ipNum;
                }
            } catch (RuntimeException var5) {
                throw new IllegalArgumentException("IP转换错误:" + ipStr, var5);
            }
        } else {
            return null;
        }
    }

    public static String convertIPv4(long ipNum) {
        return (ipNum >>> 24) + "." + ((ipNum & 16777215L) >>> 16) + "." + ((ipNum & 65535L) >>> 8) + "." + (ipNum & 255L);
    }

    public static boolean isIPv4(String ip) {
        return null == ip ? false : IPv4_PATTERN.matcher(ip).matches();
    }

    public static byte[] ipToBytesByInet(String ipAddr) {
        try {
            return InetAddress.getByName(ipAddr).getAddress();
        } catch (Exception var2) {
            throw new IllegalArgumentException(ipAddr + " is invalid IP");
        }
    }

    public static byte[] ipToBytesByReg(String ipAddr) {
        byte[] ret = new byte[4];

        try {
            String[] ipArr = ipAddr.split("\\.");
            ret[0] = (byte)(Integer.parseInt(ipArr[0]) & 255);
            ret[1] = (byte)(Integer.parseInt(ipArr[1]) & 255);
            ret[2] = (byte)(Integer.parseInt(ipArr[2]) & 255);
            ret[3] = (byte)(Integer.parseInt(ipArr[3]) & 255);
            return ret;
        } catch (Exception var3) {
            throw new IllegalArgumentException(ipAddr + " is invalid IP");
        }
    }

    public static String bytesToIp(byte[] bytes) {
        return "" + (bytes[0] & 255) + '.' + (bytes[1] & 255) + '.' + (bytes[2] & 255) + '.' + (bytes[3] & 255);
    }

    public static int bytesToInt(byte[] bytes) {
        int addr = bytes[3] & 255;
        addr |= bytes[2] << 8 & '\uff00';
        addr |= bytes[1] << 16 & 16711680;
        addr |= bytes[0] << 24 & -16777216;
        return addr;
    }

    public static int ipToInt(String ipAddr) {
        try {
            return bytesToInt(ipToBytesByInet(ipAddr));
        } catch (Exception var2) {
            throw new IllegalArgumentException(ipAddr + " is invalid IP");
        }
    }

    public static byte[] intToBytes(int ipInt) {
        byte[] ipAddr = new byte[]{(byte)(ipInt >>> 24 & 255), (byte)(ipInt >>> 16 & 255), (byte)(ipInt >>> 8 & 255), (byte)(ipInt & 255)};
        return ipAddr;
    }

    public static String intToIp(int ipInt) {
        return "" + (ipInt >> 24 & 255) + '.' + (ipInt >> 16 & 255) + '.' + (ipInt >> 8 & 255) + '.' + (ipInt & 255);
    }

    public static int[] getIPIntScope(String ipAndMask) {
        String[] ipArr = ipAndMask.split("/");
        if (ipArr.length != 2) {
            throw new IllegalArgumentException("invalid ipAndMask with: " + ipAndMask);
        } else {
            int netMask = Integer.valueOf(ipArr[1].trim());
            if (netMask >= 0 && netMask <= 31) {
                int ipInt = ipToInt(ipArr[0]);
                int netIP = ipInt & -1 << 32 - netMask;
                int hostScope = -1 >>> netMask;
                return new int[]{netIP, netIP + hostScope};
            } else {
                throw new IllegalArgumentException("invalid ipAndMask with: " + ipAndMask);
            }
        }
    }

    public static String[] getIPAddrScope(String ipAndMask) {
        int[] ipIntArr = getIPIntScope(ipAndMask);
        return new String[]{intToIp(ipIntArr[0]), intToIp(ipIntArr[1])};
    }

    public static int[] getIPIntScope(String ipAddr, String mask) {
        int netMaskInt = 0;
        boolean var4 = false;

        try {
            int ipInt = ipToInt(ipAddr);
            if (null != mask && !"".equals(mask)) {
                netMaskInt = ipToInt(mask);
                int ipcount = ipToInt("255.255.255.255") - netMaskInt;
                int netIP = ipInt & netMaskInt;
                int hostScope = netIP + ipcount;
                return new int[]{netIP, hostScope};
            } else {
                return new int[]{ipInt, ipInt};
            }
        } catch (Exception var7) {
            throw new IllegalArgumentException("invalid ip scope express  ip:" + ipAddr + "  mask:" + mask);
        }
    }

    public static String[] getIPStrScope(String ipAddr, String mask) {
        int[] ipIntArr = getIPIntScope(ipAddr, mask);
        return new String[]{intToIp(ipIntArr[0]), intToIp(ipIntArr[0])};
    }

    public static boolean isReservedAddr(InetAddress inetAddr) {
        return inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress() || inetAddr.isLoopbackAddress();
    }

    public static String getEnv(){
        return getEnv(getLocalIPv4());
    }
    public static String getEnv(String ip){
        String env = "dev";
        int ipInt = ipToInt(ip);
        Iterator<Map.Entry<String, String>> iterator = mapper.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String> next = iterator.next();
            int[] ipscope = getIPIntScope(next.getKey());
            if (ipInt >= ipscope[0] && ipInt <= ipscope[1]) {
                env = next.getValue();
                break;
            }
        }
        return env;
    }

    public static void main(String[] args) {
        System.out.println(getEnv("10.20.120.22"));
        System.out.println(getEnv());
    }
}
